﻿/*
	Copyright (C) 2019 Zongming Liu <1849059316@qq.com>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the Free Software Foundation, Inc.,
	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#ifndef Sprite_h__
#define Sprite_h__

#include "Node.h"
#include "../base/Types.h"

namespace SkyEngine2d
{
	
	class CustomCommand;
	class SpriteFrame;
	class Material;
	class TrianglesCommand;
	class Texture2D;
	
	/*!
	 \brief 精灵贴图
	 \details 
	*/
	class SGE_API Sprite
		:public Node, public IAnimatableObject
	{
		NODE_CLASS(Sprite)
	public:
	
		//! 使用图片创建一个精灵
		/*!
		\param const std::wstring & file_name  图片的路径
		\param Node* parent  精灵的父节点，默认为NULL
		\return Sprite*	精灵实例的指针。当创建精灵失败时，指针为空
		*/
		static Sprite* create(const std::wstring & file_name,Node* parent = nullptr);
	
		//! 使用精灵帧创建一个精灵
		/*!
		\param const std::shared_ptr<SpriteFrame> & sprite_frame 精灵帧的指针
		\param Node* parent	父节点
		\return Sprite*	精灵实例的指针。当创建精灵失败时，指针为空
		*/
		static Sprite* create(
			const std::shared_ptr<SpriteFrame> & sprite_frame, 
			Node* parent = nullptr
		);
	
		//! 使用 大块纹理 和 精灵在纹理中的矩形位置 创建精灵
		/*!
		\param const std::shared_ptr<Texture2D> & texture2D 纹理，这个纹理是包含多个精灵的纹理
		\param const Rect & des_rect_in_texture	精灵在纹理中的位置
		\param Node* parent 父节点
		\return Sprite* 精灵实例的指针。当创建精灵失败时，指针为空 
		*/
		static Sprite* create(
			const std::shared_ptr<Texture2D> & texture2D,
			const Rect & des_rect_in_texture,
			Node* parent = nullptr
		);
	
		//! 使用图片创建精灵，并且指定精灵在图片中的区域
		/*!
		\param const std::wstring texture_filename 图片名字
		\param const Rect & des_rect_in_texture 精灵在纹理中的位置
		\param Node* parent 父节点
		\return Sprite* 精灵实例的指针。当创建精灵失败时，指针为空 
		*/
		static Sprite* create(
			const std::wstring texture_filename,
			const Rect & des_rect_in_texture,
			Node* parent = nullptr
		);
	
		//! 设置精灵的精灵帧
		/*!
		\param const std::shared_ptr<SpriteFrame> & sprite_frame 精灵帧
		\return void 
		*/
		virtual void setSpriteFrame(const SpriteFrameSharedPtr & sprite_frame) override;
	
	
		//! 获取精灵的精灵帧 结果可能为 NULL
		/*!
		\return std::shared_ptr<SpriteFrame> 
		*/
		virtual SpriteFrameSharedPtr getSpriteFrame() const override;
	
	
		//! 设置精灵的坐标锚点
		/*!
		\param const Vector2 & anchor 锚点 值的范围为 [0，1]，默认该属性为（0.5，0.5） 
		\return void 
		*/
		void setAnchorPoint(const Vector2& anchor);
	
		//! 析构精灵对象 
		~Sprite();
		
		virtual void draw(IRender* render, const Matrix4X4& transform) override;
	
		//! 设置水平镜像
		/*!
		\param bool flip 是否镜像
		\return void  
		*/
		void setFlipH(bool flip = false);
	
	
		//! 设置垂直镜像
		/*!
		\param bool flip 是否镜像
		\return void  
		*/
		void setFlipV(bool flip = false);
	
	protected:
		//! 构造
		Sprite(Node* parent = nullptr);
		
		//! 使用文件初始化 
		/*!
		\param const std::wstring & file_name 图片文件名 
		\return bool  
		*/
		bool initWithFile(const std::wstring & file_name);
	
		//! 使用图片文件初始化
		/*!
		\param const std::wstring & file_name 图片文件
		\param const Rect & des_rect 精灵在图片中的区域  矩形为 左下角 + 尺寸
		\return bool 
		*/
		bool initWithFile(const std::wstring & file_name,const Rect & des_rect );
	
		//! 使用精灵帧初始化
		/*!
		\param const std::shared_ptr<SpriteFrame> & sf 精灵帧
		\return bool  
		*/
		bool initWithSpriteFrame(const std::shared_ptr<SpriteFrame> &sf);
	
		//! 使用纹理初始化
		/*!
		\param const std::shared_ptr<Texture2D> & tex 纹理 
		\param const Rect & des_rect 精灵在纹理中的区域 矩形为 左下角+ 尺寸
		\return bool  
		*/
		bool initWithTexture(const std::shared_ptr<Texture2D> & tex, const Rect & des_rect);
	
		//! 更新渲染资源
		/*!
		\return bool  
		*/
		bool updateRenderResource();
	
		//! 更新镜像
		/*!
		\return void 
		*/
		void updateFilp();
	
		//! 设置纹理坐标  适用于 将多个精灵纹理打包一个大的纹理 通过 `sprit_rect` 确定纹理坐标
		/*!
		\param const Rect & sprite_rect 精灵的大小
		\param V2C4T2_Quad * out_quad   将纹理位置输出到 四方形 结构中 
		\return void 
		*/
		virtual void setTextureCoords(const Rect & sprite_rect_in_tex, V2C4T2_Quad * out_quad);
	
		//! 设置顶点坐标
		/*!
		\param const Rect & sprite_rect 精灵的矩形
		\param V2C4T2_Quad * out_quad 将顶点位置输出到 四方形 结构中
		\return void  
		*/
		virtual void setVertexCoords(const  Rect & sprite_rect, V2C4T2_Quad * out_quad);
	
		//! 设置纹理
		/*!
		\param const std::shared_ptr<Texture2D> & texture 纹理
		\return void
		\note 仅仅设置 不更新 
		*/
		void setTexture(const std::shared_ptr<Texture2D>& texture);
	
	private:
	
		std::shared_ptr<Texture2D>  m_texture;
	
		//vp 矩阵
		Matrix4X4	m_vpMatrix;
		//精灵帧
		mutable std::shared_ptr<SpriteFrame> m_spriteFrame;
		//材质
		std::shared_ptr<Material> m_material;
		//渲染命令
		std::shared_ptr<TrianglesCommand> m_cmd;
		
		V2C4T2_Quad m_quad;
	
		//是否开启水平轴镜像
		bool m_isFlipH;
		//是否开启垂直镜像
		bool m_isFlipV;
	
		Vector2   m_anchorPoint;
	
		FRIEND_SMART_PTR(Sprite)
	};
	
}

#endif // Sprite_h__
